﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace KgUtils.Core
{
    /// <summary>
    /// Classe permettant de créer un IEqualityComparer "jetable", sans avoir à créer la classe ou à l'implémenter dans la classe à comparer.
    /// </summary>
    /// <typeparam name="T">Le type à comparer</typeparam>
    public class GenericComparer<T> : IEqualityComparer<T>
    {
        private readonly Func<T, T, bool> _comparer;
        private readonly Func<T, int> _hashCodeResolver;

        /// <summary>
        /// Initialise le GenericComparer en indiquant la méthode de comparaison et en utilisant le GetHashCode de l'objet T.
        /// </summary>
        /// <param name="comparer">La méthode utilisée pour effectuer la comparaison des objets.</param>
        public GenericComparer(Func<T, T, bool> comparer)
            : this(comparer, null)
        {
        }

        /// <summary>
        /// Initialise le GenericComparer en indiquant la méthode de comparaison et la méthode permettant de calculer le GetHashCode.
        /// </summary>
        /// <param name="comparer">La méthode utilisée pour effectuer la comparaison des objets.</param>
        /// <param name="hashCodeResolver">La méthode utilisée pour calculer le HashCode de l'objet.</param>
        public GenericComparer(Func<T, T, bool> comparer, Func<T, int> hashCodeResolver)
        {
            Guard.AssertNotNull(comparer, "comparer");

            _comparer = comparer;
            _hashCodeResolver = hashCodeResolver;
        }

        #region Interface IEqualityComparer<T>
        public bool Equals(T x, T y)
        {
            return _comparer(x, y);
        }

        public int GetHashCode(T obj)
        {
            if (_hashCodeResolver != null)
                return _hashCodeResolver(obj);
            else
                return obj.GetHashCode();
        }
        #endregion
    }
}
